package mathE;

import java.util.ArrayList;
import java.util.Collection;

import mathE.exception.FuctionException;
import swg.shape.Branch;
import swg.shape.Color;
import swg.shape.IswgShape;
import swg.shape.Point;
import swg.shape.Polyline;
import swg.shape.Text;
import swg.utils.Utils;

public abstract class Function 
{
	public abstract double f(double x);
	
	public double integral(double a, double b, double steps) throws FuctionException{

		double res=0;
		double gap = (b-a)/steps;
		for(double  i =0.0;i<steps-1;i++){
			double xa = a+gap*i;
			double xb= a+(gap)*(1.0+i);
			double ya = f(xa);
			double yb = f(xb);
			res = res +(ya+yb)*gap /2.0;			
		}
		
		return res;
	}
	
	public double integralCS(double a, double b, double steps) throws FuctionException{
		System.out.println("a:"+a);
		System.out.println("b:"+b);
		System.out.println("steps:"+steps);
		double res=0;
		double gap = Math.abs(b-a)/steps;
		for(double x=a;  x<b  ; x=x+gap*2){
			double x1=x;
			double x2=x+gap;			
		
			
			res = res +gap/3.0*(4*f(x1)+2*f(x2));		
		}
		
		
		return res;
	}
	
	public ArrayList<IswgShape> graphSVG(double xmin, double  xMax, int xDot){

		int xspan=20;
		int yspan=20;
		ArrayList<IswgShape> res  = new ArrayList<IswgShape>();
		double[][] points = new double[xDot][2];
		double ymin=Double.MAX_VALUE;
		double yMax=-Double.MAX_VALUE;
		double step=(xMax-xmin)/(xDot*1.);
		for(int i=0;i<xDot;i++ ){
			double x=xmin+step*(i*1.);
			double y = f(x);
			if (y<ymin)
				ymin=y;

			if (y>yMax)
				yMax=y;
			points [i][0]=x;
			points [i][1]=y;
		}
		
		double xGmin=0;
		double xGMax=xDot;
		
		double yGmin=0;
		double yGMax=xDot;

		//double deltaxG=Math.abs(xGMax-xGmin);
		double deltayG=Math.abs(yGMax-yGmin);
		

		//double deltaxF=Math.abs(xMax-xmin);
		double deltayF=Math.abs(yMax-ymin);
		
		double scale = deltayG/deltayF;
		String style= "font-family: Arial;font-size  : 8px;fill       : #00ff00;";

//		ArrayList<Point> funz = new ArrayList<Point>();		
//		for(int i=(int) xGmin; i<xGMax;i++){
//			int y = (int) (ymin+points[i][1]*scale)+yspan;
//			Point p = new Point(i+xspan, y+xspan);
//			funz.add(p);
//			if (i%(xDot/10)==0){
//				Text t = new Text(i+xspan, y,Utils.concat("(",points[i][1],",",points[i][0],")"),style);
//				Circle c = new Circle(i+xspan, y+xspan,2);
//				res.add(t);
//				res.add(c);
//			}
//		}
//		Polyline gFunz= new Polyline("fill:none;stroke-width:1;stroke:grey", funz);	
//		res.add(gFunz);
		res.addAll(createCartesianPlane(xGmin,xGMax,yGmin,yGMax, xspan, yspan,xmin,xMax, ymin, yMax));
		return res;
	}

	private Collection<? extends IswgShape> createCartesianPlane(
			double xGmin, double xGMax, 
			double yGmin, double yGMax, 
			int xspan, int yspan, 
			double xmin, double xMax, 
			double ymin, double yMax)
	{
		Color c = new Color(150);
		ArrayList<IswgShape> res  = new ArrayList<IswgShape>();
		Polyline box = Polyline.getBox(xGmin+xspan,xGMax+xspan,yGmin+yspan,yGMax+yspan,"fill:none;stroke-width:1;stroke:grey");
		Branch axisX = new Branch(new Point(xGmin+xspan,yGMax/2+yspan), new Point(xGMax+xspan, yGMax/2+yspan));
		axisX.setStyleStrike(1);
		axisX.setStyleColor(c);

		double arrowLengh=12;
		double arrowWidth=8;
		double ticLengh=8;
		
		ArrayList<Point> arrow = new ArrayList<Point>();	
		arrow.add(new Point(xGMax+xspan-arrowLengh, yGMax/2+yspan));
		arrow.add(new Point(xGMax+xspan-arrowLengh, yGMax/2+yspan-arrowWidth/2));
		arrow.add(new Point(xGMax+xspan, yGMax/2+yspan));
		arrow.add(new Point(xGMax+xspan-arrowLengh, yGMax/2+yspan+arrowWidth/2));
		arrow.add(new Point(xGMax+xspan-arrowLengh, yGMax/2+yspan));
		Polyline arrowX = new Polyline("fill:grey;stroke:grey;stroke-width:0",arrow);
		


		double deltaX=(Math.abs(xMax-xmin))/((Math.abs(xGMax-xGmin)));
		double deltaY=(Math.abs(yMax-ymin))/((Math.abs(yGMax-yGmin)));

		String style= "font-family: Arial;font-size  : 10px;fill: #0000ff;";
		

		int yy=(int)(yGMax/2+ticLengh*1.5+yspan);
		for (int i = (int) xGmin; i< xGMax; i=i+20){
			Branch tic= new  Branch(new Point(i+xspan,yGMax/2+ticLengh/2+yspan), new Point(i+xspan,yGMax/2-ticLengh/2+yspan));
			tic.setStyleStrike(1);
			tic.setStyleColor(c);
			res.add(tic);
			int xx=i+xspan;
			String transform=Utils.concat("rotate(",45," ",xx,",",yy,")");
			double number = Math.ceil(((xmin+deltaX*(i*1.))*10+.5))/10;
			Text t = new Text(xx,yy, number+"",style, transform);
			res.add(t);
		}
		

		int xx=(int)(xGMax/2-ticLengh*2+xspan);
		for (int i = (int) yGmin; i< yGMax; i=i+20){
			
			Branch tic= new  Branch(new Point(xGMax/2+ticLengh/2+xspan,i+yspan), new Point(xGMax/2-ticLengh/2+xspan,i+yspan));
			tic.setStyleStrike(1);
			tic.setStyleColor(c);
			res.add(tic);
			

			yy=i+yspan;
			String transform=Utils.concat("rotate(",45," ",xx,",",yy,")");
			double number = Math.ceil(((ymin+deltaY*(i*1.))*10+.5))/10;
			Text t = new Text(xx,yy, number+"",style, transform);
			res.add(t);
		}
		
		
		
		Branch axisY=  new Branch(new Point(xGMax/2+xspan,yGmin+yspan), new Point(xGMax/2+xspan, yGMax+yspan));
		axisY.setStyleStrike(1);
		axisY.setStyleColor(c);
		

		arrow = new ArrayList<Point>();	
		arrow.add(new Point(xGMax/2+xspan, 0+yspan+arrowLengh));
		arrow.add(new Point(xGMax/2+xspan-arrowWidth/2, 0+yspan+arrowLengh));
		arrow.add(new Point(xGMax/2+xspan,0+yspan));
		arrow.add(new Point(xGMax/2+xspan+arrowWidth/2, 0+yspan+arrowLengh));
		arrow.add(new Point(xGMax/2+xspan, 0+yspan+arrowLengh));
		Polyline arrowY = new Polyline("fill:grey;stroke:grey;stroke-width:1",arrow);
		
		res.add(box);
		res.add(axisX);
		res.add(arrowX);
		res.add(axisY);
		res.add(arrowY);
		return res;
	}
}
